#pragma once
#include <QObject>
#include <QQmlContext>
#include <QSharedPointer>
#include <QThread>
#include <QtConcurrent>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QNetworkInterface>
#include "../../core/cbase.h"

class QUtil {
public:
    static void doInUiThread(const std::function<void(void)>& func);

    static void doInObjectThread(QObject* object, const std::function<void(void)>& func);

    static void delayExecute(const std::function<void(void)>& func, int intervalMs, Qt::TimerType timerType = Qt::CoarseTimer);

    static void loopExecute(const std::function<void(void)>& func, int intervalMs, Qt::TimerType timerType = Qt::PreciseTimer, Qt::ConnectionType connType = Qt::AutoConnection);
    static void loopSeamless(const std::function<void()>& func);
    static void loopExecuteTerminable(const std::function<bool(void)>& func, int intervalMs, Qt::TimerType timerType = Qt::CoarseTimer, int startUpDelayMs = 0);

    static QThread* loopInNewThread(const std::function<void(void)>& func, int intervalMs, Qt::TimerType timerType = Qt::CoarseTimer);

    static void destroyThread(QThread*& thread);
    static void destroyTimer(QTimer*& timer);

    static void printCurrentQThread(const QString& tag = "");

    inline static QString currentTime() { return QTime::currentTime().toString("hh:mm:ss:zzz"); }

    inline static bool isMainThread() { return QThread::currentThread() == QCoreApplication::instance()->thread(); }

    /**
    * @brief append to the event-loop, do not execute immediately, otherwise, may lead to timing issues!
    */
    static void appendEventLoop(QObject* context, const std::function<void()>& func) { QMetaObject::invokeMethod(context, func, Qt::QueuedConnection); }

    static void handleCommandArgs(const QString& name, const QString& description, const std::function<void(void)>& func);

    static void enableQtEnvLog(const CStringList& logCategories);

    static void getLocalIP(QHostAddress* out_eth0_ip, QHostAddress* out_wlan0_ip = nullptr);

    //template<typename T>
    //static void qmlRegisterType(const char* uri, int versionMajor, int versionMinor, const char* qmlName) { qmlRegisterType<T>(uri, versionMajor, versionMinor, qmlName); }

    //static void setContextProperty(QQmlContext* qmlContext, const QString& name, QObject* object) { qmlContext->setContextProperty(name, object); }
};